#include "Music.h"
#include <unistd.h>
#include <dirent.h>
#include "MusicObj.h"
#include "lrc.h"

#define MUSIC_DIR "/overlay/musics/"
#define LYRIC_DIR "/overlay/musics/lyric/"

static int thread_func(Music *obj);
static int music_get_state(void);
static void music_pause(void);
static void music_play(const char *name, int index);
static void music_set_cur(int cur_sec);
static void music_set_mode(MusicMode mode);
static MusicMode music_get_mode(void);
static void changeMusic(Music *obj);

//当前播放音乐索引
static int musicIndex = 0;

//当前播放的音乐
static MusicObj *musicObj = NULL;

//当前播放音乐的歌词
static lyric_t *musicLyric = NULL;

//音乐播放模式
static MusicMode musicMode = MusicMode_ListLoop;         //音乐播放模式

//UI互斥锁
static mutex *ui_mutex = nullptr;

/*
  *@brief MainPage构造函数
  *@param exit_cb 退出进程回调函数
  */
Music::Music(exit_cb_t exit_cb, mutex &UIMutex)
{
    thread_exit_flag = false;
    ui_mutex = &UIMutex;

    //设置UI回调函数
    gui_opt_t gui_opts = {0};
    gui_opts.exit_cb = exit_cb;
    gui_opts.music_get_state = music_get_state;
    gui_opts.music_pause = music_pause;
    gui_opts.music_play = music_play;    
    gui_opts.music_set_cur = music_set_cur;
    gui_opts.music_set_volume = snd_set_volume;
    gui_opts.music_get_volume = snd_get_volume;
    gui_opts.music_get_mode = music_get_mode;
    gui_opts.music_set_mode = music_set_mode;

    music_gui_init(&gui_opts);

    pthread = new thread(thread_func, this);           //创建执行线程
}

Music::~Music()
{
    thread_exit_flag = true;
    pthread->join();
    delete pthread;

    music_gui_release();
}

/*
  *@brief 搜索某个目录下的音频文件,支持MP3 WAV
  *@param path 目录路径
  *@return 搜索到的音乐个数
  */
int Music::searchMusic(string path)
{
    int cnt_r = 0;
    int i;
    bool legal_music = false;
    std::string file_path;

    struct dirent *ent;
    DIR *dir = opendir(path.c_str());

    for (i = 0; ; i++)
    {
        ent = readdir(dir);
        if (ent == NULL)
            break;

        if (ent->d_type == DT_REG)
        {
            const char *pfile = strrchr(ent->d_name, '.');
            if (pfile != NULL)
            {
                file_path = path + std::string(ent->d_name);

                if (strcasecmp(pfile, ".wav") == 0)
                {
                    printf("wav file\n");
                    legal_music = true;
                }
                else if (strcasecmp(pfile, ".mp3") == 0)
                {
                    printf("mp3 file\n");
                    legal_music = true;
                }

            }
        }
        if (legal_music == true)
        {
            legal_music = false;
            ui_mutex->lock();
            music_gui_add_music_list(ent->d_name);
            ui_mutex->unlock();
            
            cnt_r++;
        }

        usleep(50000);
    }

    closedir(dir);

    return cnt_r;
}

static int thread_func(Music *obj)
{
    int tick = 0;
    usleep(50000);

    obj->searchMusic(MUSIC_DIR);

    while (!obj->getExitFlag())
    {
        ui_mutex->lock();

        if(musicObj != NULL)
            music_gui_set_progress(musicObj->getCurTime(), musicObj->getTotalTime());
        if(musicLyric != NULL)
        {
            int id =lyric_getid_by_time(musicLyric, musicObj->getCurTime() * 1000);
            music_gui_set_lyric_id(id);
        }

        if(tick++ == 10)
        {
            tick = 0;
            if(musicObj != NULL && musicObj->isOver() == true)
                changeMusic(obj);           //根据当前模式切歌
        }
        ui_mutex->unlock();

        usleep(100000);
    }

    if(musicObj != NULL)
        delete musicObj;

    return 0;
}

/*
  *@brief 切歌
  */
static void changeMusic(Music *obj)
{
    int max_index = obj->getMusicNum() - 1;

    switch(musicMode)
    {
        case MusicMode_ListLoop:
            musicIndex = musicIndex < max_index ? musicIndex + 1 : 0;           //顺序递增索引
        break;
        case MusicMode_SingleLoop:
            //musicIndex = musicIndex;                  //索引不变
        break;
        case MusicMode_Random:
        musicIndex = rand() % (max_index + 1);          //随机生成索引
        break;
    }
    const char *name = music_gui_get_music_name(musicIndex);            //根据索引获取音乐文件名

    music_play(name, musicIndex);           //播放
}

/*
  *@brief 获取当前音乐的状态
  *@return 音乐状态 0 - 暂停状态       1 - 播放状态   -1 - 未播放(或播放结束)
  */
static int music_get_state(void)
{
    if(musicObj != NULL && musicObj->threadState != false)
        return (int)musicObj->getPlayState();
    else
        return -1;
}

/*
  *@brief 暂停音乐播放
  */
static void music_pause(void)
{
    if(musicObj != NULL)
        musicObj->pause();
}

/*
  *@brief 播放音乐
  *@param name 切换的音乐文件名，若为NULL则继续播放当前音乐
  *@param index 切换的音乐索引
  */
static void music_play(const char *name, int index)
{
    if(name == NULL)                //不需要切歌
    {
        if(musicObj != NULL)
            musicObj->play();
        return;
    }

    musicIndex =index;          //保存播放索引
    music_gui_show_music_name(name);            //设置音乐名显示

    string filePath = MUSIC_DIR +  string(name);
    if(musicObj != NULL)
        delete musicObj;            //删除先前的播放
    musicObj = NULL;

    if(musicLyric != NULL)  
        lyric_free(musicLyric);         //删除先前的歌词
    musicLyric = NULL;

    musicObj = new MusicObj(filePath);
    musicObj->play();

    filePath = LYRIC_DIR + string(name);
    size_t pos = filePath.find('.');
    if(pos != string::npos)
    {
        filePath.erase(pos);
        filePath += ".lrc";
        musicLyric = lyric_load_from_file(filePath.c_str());
        if(musicLyric != NULL)
        {
            const char *lyric_all = lyric_get_all(musicLyric, '\n');
            music_gui_load_lyric(lyric_all);            //装载歌词到UI
            if(lyric_all != NULL)
                free((void *)lyric_all);
        }
        else
            music_gui_load_lyric(NULL);            //指示找不到歌词
    }
    
}

/*
  *@brief 设置音乐播放时间点
  *@param cur_sec 设置的播放时间点，单位sec
  */
static void music_set_cur(int cur_sec)
{
    if(musicObj != NULL)
        musicObj->setCurTime(cur_sec);
}

/*
  *@brief 设置音乐播放模式
  *@param mode
  */
static void music_set_mode(MusicMode mode)
{
    musicMode = mode;
}

/*
  *@brief 获取当前音乐播放模式
  *@param mode
  */
static MusicMode music_get_mode(void)
{
    return musicMode;
}